
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "main-tools.h"
#include "memory-tools.h"
#include "lexer.h"
#include "semantic.h"

//used to disable the implicit-function-declaration warning shwon on the call of yyparse()
//#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"

/**represents that this test is successful*/
#define TEST_SUCCESS 1
/**represents that this test is failed*/
#define TEST_FAILURE 0
/**represents that this test is skipped (cause is present in TESTSUITE_TESTEXCLUDED )*/
#define TEST_SKIPPED 2

/**represents the number of total tests in this suite, both included and excluded.*/
#define TESTSUITE_LENGTH 2
/**indicates a list of test IDs which won't be executed. Use commas (",") as separator*/
#define TESTSUITE_TESTEXCLUDED

#include "parser.h"
#include "lexer.h"
#include "parser-tools.h"

int (*testcase[TESTSUITE_LENGTH])(void);

/**tests:
 * \li if a semantiic correct label file generate a correct label table
 *
 * @return TRUE if there are no memory leaks
 */
bool test00(){
	initLibrary();
	FILE* f=fopen("yaoola_src/sym_test00.yaoola","r");
	int result;

	extern PSyntaxNode root;
	LabelHashTable labelhashtable;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("Initial memory used: %d\n",getMemoryAllocated());
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	printf("tree read.\n");
	printf("Syntax Tree size: %d\n",getMemoryAllocated());
	printf("initialize label table...\n");
	initLabelHashTable(&labelhashtable);
	printf("Computing Symbol table...\n");
	int a=getMemoryAllocated();
	sym(root,&labelhashtable,NULL);
	int b=getMemoryAllocated();
	printf("DONE. Showing label table...\n");
	result=buildLabelHashTableGraph("symboltable_test00",&labelhashtable);
	printf("label table size: %d\n",b-a);
	printf("DONE. Now freeing symbol table...\n");
	freeLabelHashTable(&labelhashtable);
	//printf();
	printf("DONE. Now freeing syntax tree...\n");
	freeSyntaxTree(root);
	printf("DONE.\n");
	fclose(f);
	printf("memory leak: %d\n",getMemoryAllocated());
	if (getMemoryAllocated()==0){
		return true;
	}
	return false;
}

/**tests these type of errors:
 * \li modifiers present in label file other than PUBLIC and PACKAGE;
 * \li 2 same label present in the same label file
 *
 * @return
 */
bool test01(){
	initLibrary();
	FILE* f=fopen("yaoola_src/sym_test01.yaoola","r");
	int result;

	extern PSyntaxNode root;
	LabelHashTable labelhashtable;
	if (f==NULL){
		printf("source file not found");
		return false;
	}
	printf("setting yylex...");
	yylex_destroy();
	yyrestart(f);
	yyset_in(f);
	printf("Initial memory used: %d\n",getMemoryAllocated());
	printf("building tree...\n");
	result=yyparse();
	if (result!=0){
		printf("tree not read.\n");
		return false;
	}
	printf("tree read.\n");
	printf("Syntax Tree size: %d\n",getMemoryAllocated());
	printf("initialize label table...\n");
	initLabelHashTable(&labelhashtable);
	printf("Computing Symbol table...\n");
	int a=getMemoryAllocated();
	int start_position=ftell(stderr);
	sym(root,&labelhashtable,NULL);
	int end_position=ftell(stderr);
	int b=getMemoryAllocated();
	printf("DONE. Showing label table...\n");
	result=buildLabelHashTableGraph("symboltable_test01",&labelhashtable);
	printf("label table size: %d\n",b-a);
	printf("DONE. Now freeing symbol table...\n");
	freeLabelHashTable(&labelhashtable);
	printf("DONE. Now freeing syntax tree...\n");
	freeSyntaxTree(root);
	printf("DONE.\n");
	fclose(f);
	printf("memory leak: %d\n",getMemoryAllocated());
	if (getMemoryAllocated()!=0){
		return false;
	}
	if (start_position!=end_position){
		return false;
	}
	return false;
}

bool setUp(){
	/* ************** TESTCASE Construction ***********************/
	testcase[0]=(void*)test00;
	testcase[1]=(void*)test01;
	/* ************ OTHER ******************/
	return true;
}

bool tearDown(){
	return true;
}

int main(){
	if (setUp()==false){
		printf("SETUP FAILED.\n");
		return EXIT_FAILURE;
	}
	printf("SETUP SUCCESSFUL\n");

	int i,j;
	int excluded[]={TESTSUITE_TESTEXCLUDED};
	int testResults[TESTSUITE_LENGTH];
	int failed_tests=0;
	bool toskip;

	for(i=0;i<TESTSUITE_LENGTH;i++){
		//check if the test ID i is present in the excluded array. If it is the test must be skipped
		toskip=false;
		for (j=0;j<(sizeof(excluded)/sizeof(excluded[0]));j++){
			if(excluded[j]==i){
				toskip=true;
				break;
			}
		}
		if (toskip==true){
			testResults[i]=TEST_SKIPPED;
			continue;
		}
		printf("############# Running now test case %d ##############\n",i);
		testResults[i]=(*testcase[i])();
		if (testResults[i]==true){
			printf("Test case #%d successful.\n",i);
		}else{
			printf("Test case #%d failed.\n",i);
			failed_tests++;
		}
	}

	printf("####################################################\n");
	if (tearDown()==false){
		printf("TEAR DOWN FAILED.\n");
		return EXIT_FAILURE;
	}
	printf("TEAR DOWN SUCCESSFUL.\n");
	printf("-------------------------------------------\n");
	printf("Summary of this suite:\n");
	for (i=0;i<TESTSUITE_LENGTH;i++){
		printf("Test #%d: ",i);
		switch (testResults[i]){
		case TEST_SUCCESS: {
			printf("success");
			break;
		}
		case TEST_FAILURE: {
			printf("failure");
			break;
		}
		case TEST_SKIPPED: {
			printf("skipped");
			break;
		}
		default: {
			printf("??? (%d)",testResults[i]);
			break;
		}
		}
		printf("\n");
	}
	printf("number of test failed: %d\n",failed_tests);
	printf("--------------------------------\n");
	printf("TEST SUITE FINISHED\n");
	return EXIT_SUCCESS;
}
